package websocketIoServer;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 实现了一个原生的ws服务器 可以进行客户端的管理和数据的收发
 */
public class WebServer {
    private ServerSocket serverSocket;
    List<SocketBean> socketList = new ArrayList<>();

    ExecutorService executorService = Executors.newFixedThreadPool(4);
    public void run(int port) throws IOException {
        executorService.execute(()->{
            try {
                serverSocket = new ServerSocket(port);
            while (true) {
                Socket socket = serverSocket.accept();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
                String line;

                char[] buffer = new char[1024];
                int length = 0;
                StringBuilder str = new StringBuilder();
                while (true) {
                    length = bufferedReader.read(buffer);
                    str.append(buffer,0,length);
                    //表示数据以读完
                    if (length <= 0 || length < 1024) {
                        break;
                    }
                }

                System.out.println(str.toString());
                WsProtocol.Header wsHeader = WsProtocol.Header.decodeFromHeadShakeDate(str.toString());
                SocketBean socketBean = new SocketBean(socket,wsHeader);
                socketList.add(socketBean);

                String resp = WsProtocol.getHandShakeResp(socketBean.header.getHeader("Sec-WebSocket-Key"));
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socketBean.socket.getOutputStream(), "GBK"));
                writer.write(resp);
                writer.flush();
            }

            }catch (Exception e){
                e.printStackTrace();
                System.out.println("异常");
            }
        });
        executorService.execute(()->{
            byte[] sd = new byte[1];
            while (true){
                for (SocketBean item:socketList) {
                    try {
                        InputStream bufferedInputStream = item.socket.getInputStream();
                        if (bufferedInputStream.available() == 0){
                            continue;
                        }
                        byte[] buffer = new byte[1024];
                        int length = 0;
                        StringBuilder str = new StringBuilder();
                        while (true) {
                            length = bufferedInputStream.read(buffer);
                            //opcode为8，对方主动断开连接
                            System.out.println("opcode:"+(buffer[0] & 0xf));
                            if ((buffer[0] & 0xf) == 8) {
                                throw new IOException("session disconnect.");
                            }

                            byte payloadLength = (byte) (buffer[1] & 0x7f);
                            System.out.println("数据长度 "+payloadLength);
                            System.out.println("buffer "+Arrays.toString(buffer));
                            byte[] mask = Arrays.copyOfRange(buffer, 2, 6);
                            byte[] payloadData = Arrays.copyOfRange(buffer, 6,length);
                            for (int i = 0; i < payloadData.length; i++) {
                                payloadData[i] = (byte) (payloadData[i] ^ mask[i % 4]);
                            }

                            str.append(new String(payloadData,0,length-6,"GBK"));
                            str.append("===============");
                            str.append(new String(payloadData,0,length-6,"UTF-8"));
                            str.append("===============");
                            //表示数据以读完
                            if (length <= 0 || length < 1024) {
                                break;
                            }
                        }
                        System.out.println("ads"+str);

//                socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        });


        while (true){
            Scanner scanner = new Scanner(System.in);
            String resp = scanner.nextLine();
            socketList.forEach(item->{
                try {
                    byte[] boardCastData = new byte[2 + resp.getBytes().length];
                    boardCastData[0] = (byte) 0x81;
                    boardCastData[1] = (byte) resp.getBytes().length;
                    System.arraycopy(resp.getBytes(), 0, boardCastData, 2, resp.getBytes().length);
                    System.out.println(Arrays.toString(boardCastData));
                    OutputStream writer = item.socket.getOutputStream();

                    writer.write(boardCastData);
                    writer.flush();
//                socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }


    }
}
